<?php
/**
 * @package    panel
 * @subpackage panel.application
 */
/**
 * panel.application response object
 * Used to store response given from RRP
 * and output according to response type (_rt) defined in request.
 *
 * @author Dmitry Bakaleinik (code)
 */
class panel__application__response
	implements maf__mvc__i__view {

	/**
	 * Known content types.
	 */
	const TYPE__TEXT__HTML          = "text/html";
	const TYPE__TEXT__HTML__EJSON   = "text/html/ejson";
	const TYPE__TEXT__CSS           = "text/css";
	const TYPE__TEXT__JSON          = "text/json";
	const TYPE__TEXT__JSON_HTML     = "text/json/html";
	const TYPE__TEXT__JAVASCRIPT    = "text/javascript";
	const TYPE__TEXT__XML           = "text/xml";
	const TYPE__TEXT__PLAIN         = "text/plain";
	const TYPE__NULL				= "null";
	const TYPE__DBUG                = "dbug";
	const TYPE__DBUG__RECORDSET     = "dbug/recordset";
	const TYPE__VAR_EXPORT          = "var_export";
	const TYPE__PANEL__LAYOUT       = "panel/layout";

	/**
	 * @var mixed Response data
	 */
	protected $response;

	/**
	 * @var string Response type
	 */
	protected $type;

	/**
	 * @var array Response headers to be sent
	 */
	protected $headers = array();

	/**
	 * Setup default content-type for response
	 */
	public function __construct() {

		$this->type = self::TYPE__TEXT__HTML;

	}	# Function

	/**
	 * Send HTTP headers corresponding to response content-type
	 * @return bool
	 */
	protected function processHeaders() {

		switch( $this->type ) {

		case self::TYPE__TEXT__CSS:
			header("Content-type: text/css; charset=UTF-8", TRUE);
			break;

		case self::TYPE__TEXT__PLAIN:
			header("Content-type: text/plain; charset=UTF-8", TRUE);
			break;

		case self::TYPE__DBUG:
		case self::TYPE__DBUG__RECORDSET:
		case self::TYPE__VAR_EXPORT:
		case self::TYPE__PANEL__LAYOUT:
		case self::TYPE__TEXT__HTML:
		case self::TYPE__TEXT__HTML__EJSON:
		case self::TYPE__TEXT__JSON_HTML:
			header("Content-type: text/html; charset=UTF-8", TRUE);
			break;

		case self::TYPE__TEXT__JSON:
			header("Content-type: text/json; charset=UTF-8", TRUE);
			break;

		case self::TYPE__TEXT__JAVASCRIPT:
			header("Content-type: text/javascript; charset=UTF-8", TRUE);
			break;

		case self::TYPE__TEXT__XML:
			header("Content-type: text/xml; charset=UTF-8", TRUE);
			break;

		case self::TYPE__NULL:
			break;

		default:
			throw new panel__e__unknown_response_type($this->type);
			break;

		}	# switch

		foreach($this->headers as $_header) {

			if( isset($_header["code"]) ) {

				header($_header["message"], TRUE, $_header["code"]);

			} else {

				header($_header["message"], TRUE);

			}	# if

		}	# foreach

		return TRUE;

	}	# Function

	/**
	 * Convert stored response data to
	 * requested (_rt) response type.
	 *
	 * @param  boolean $_silent_
	 * @return mixed
	 */
	protected function processResponse($_silent_) {

		switch( $this->type ) {

		case self::TYPE__NULL:
			return;
			break;

		case self::TYPE__TEXT__JSON:
		case self::TYPE__TEXT__JSON_HTML:
			$response = json_encode($this->response);
			break;

		case self::TYPE__TEXT__CSS:
		case self::TYPE__TEXT__HTML:
		case self::TYPE__TEXT__JAVASCRIPT:
		case self::TYPE__TEXT__HTML__EJSON:
		case self::TYPE__TEXT__PLAIN:
			$response = $this->response;
			break;

		case self::TYPE__PANEL__LAYOUT:

			$ui = new panel__rrp__ui;
			$response = $ui->process("layout", $this->response, $this);

			break;

		case self::TYPE__DBUG:

			new dBug($this->response);
			$response = "";

			break;

		case self::TYPE__DBUG__RECORDSET:
			new dBug($this->response, "recordset");
			$response = "";
			break;

		case self::TYPE__VAR_EXPORT:
			$response = "<pre>" . var_export($this->response, TRUE) . "</pre>";
			break;

		case self::TYPE__TEXT__XML:

			if( $this->response instanceOf XMLWriter ) {

				$response = $this->response->outputMemory();

			} else {

				$response = $this->response;

			}	# if

			break;

		default:
			throw new panel__e__unknown_response_type($this->type);
			break;

		}	# switch

		if( isset_or($_REQUEST["_pre"]) ) {
			echo "<pre>"; }

		if( !$_silent_ ) {

			header("Content-Length: " . strlen((string) $response) . " ;");
			echo $response;

		}	# if

		if(
			is_string($response) &&
			panel__settings__environment
			::isVerbose("panel.application.response.response_length")
		) {

			panel__application::console(
				"Response length: " . strlen($response)
			);

		}	# if

		return $response;

	}	# Function

	/**
	 * API call used for generate response headers and data
 	 *
	 * @param  string $_silent_ Do not produce output
	 * @return string
	 */
	public function process( $_silent_ = FALSE ) {

		$this->processHeaders();

		return $this->processResponse($_silent_);

	}	# Function

	/**
	 * Set response data
	 *
	 * @param mixed $_
	 */
	public function setResponse($_) {

		$this->response = $_;

	}	# Function

	/**
	 * Set response type
	 *
	 * @param string $_
	 */
	public function setType($_) {

		$this->type = (string) $_;

	}	# Function

	/**
	 * Add header
	 *
	 * If message = NULL then it will be completed by default message
	 * according to code value.
	 *
	 * @param  string|null $_message_ Message
	 * @param  int         $_code_    Header code
	 * @return bool
	 */
	public function addHeader($_message_, $_code_ = NULL) {

		if( is_null($_message_) ) {	switch($_code_) {

		case 500: $_message_ = "HTTP/1.1 500 Internal Server Error"; break;
		case 404: $_message_ = "HTTP/1.0 404 Not Found"; break;
		case 403: $_message_ = "HTTP/1.0 403 Forbidden"; break;

		} }	# if

		$this->headers[] = array(
			"message" => $_message_,
			"code"    => isset_or($_code_)
		);

		return TRUE;

	}	# Function

	/**
	 * Clear all response headers
	 */
	public function clearHeaders() {

		$this->headers = array();

	}	# Function

	/**
	 * Get all response header
	 *
	 * @return array
	 */
	public function getHeaders() {

		return $this->headers;

	}	# Function

	/**
	 * Return response data
	 *
	 * @return mixed
	 */
	public function getResponse() {

		return $this->response;

	}	# Function

}	# Class

/* EOF */